﻿using System;
using System.Collections.Generic;
using System.Reflection;
using NUnit.Core;
using SqlTdd.Core.Model;

namespace SqlTdd.Addin
{
    public class TestCatalogBuilder : TestSuite
    {
        public TestCatalogBuilder(Type fixtureType) : base(fixtureType)
        {
            Fixture = Reflect.Construct(fixtureType);
            ITestFactory factory = new TestFactory();

            List<SqlTddTestSchema> catalog = factory.GetTestCatalog();

            foreach (
                MethodInfo templateMethod in
                    fixtureType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
            {
                BuildTestSuites(factory, catalog, templateMethod);
            }
        }

        private void BuildTestSuites(ITestFactory factory, List<SqlTddTestSchema> catalog, MethodInfo templateMethod)
        {
            foreach (SqlTddTestSchema schema in catalog)
            {
                Add(BuildSqlTddSchemaAsNUnitTestSuite(schema, templateMethod, factory));
            }
        }

        private TestSuite BuildSqlTddSchemaAsNUnitTestSuite(SqlTddTestSchema schema, MethodInfo templateMethod,
                                                            ITestFactory factory)
        {
            var nUnitSchemaSuite = new TestSuite(schema.Name);

            foreach (SqlTddTestSuite suite in schema.TestSuites)
            {
                nUnitSchemaSuite.Add(BuildSqlTddTestSuiteAsNUnitTestSuite(suite, templateMethod, factory));
            }
            return nUnitSchemaSuite;
        }

        private TestSuite BuildSqlTddTestSuiteAsNUnitTestSuite(SqlTddTestSuite suite, MethodInfo templateMethod,
                                                               ITestFactory factory)
        {
            var nUnitSuite = new TestSuite(suite.Name);
            foreach (SqlTddTestMethod method in suite.TestMethods)
            {
                nUnitSuite.Add(new TestMethodBuilder(templateMethod, method, factory.ConnectionString()));
            }
            return nUnitSuite;
        }
    }
}